home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 3 / Cream of the Crop 3.iso / comm / wnos5src.zip / NNTPSERV.C < prev    next >
Text File  |  1993-08-09  |  20KB  |  946 lines

  1. /*
  2.  *
  3.  * NNTP Server - See RFC977
  4.  * Jeffrey R. Comstock. - NR0D - Bloomington, Minnesota USA
  5.  * Copyright 1990 Jeffrey R. Comstock, All Rights Reserved.
  6.  * Permission granted for non-commercial copying and use, provided
  7.  * this notice is retained.
  8.  *
  9.  * DB3FL 9107xx: heavily rewritten and bug fixing in file-handling
  10.  * DB3FL 920121: splitted into several files
  11.  *
  12.  */
  13. #include <dos.h>
  14. #include <time.h>
  15. #include <ctype.h>
  16. #include <string.h>
  17. #include <io.h>
  18.  
  19. #include "global.h"
  20. #include "config.h"
  21. #ifdef NNTP
  22. #include "nntp.h"
  23. #include "socket.h"
  24. #include "files.h"
  25. #include "ftp.h"
  26. #ifdef LZW
  27. #include "lzw.h"
  28. #endif
  29. #include "server.h"
  30.  
  31. #undef CONTROL                /* (not implemented yet) */
  32. #undef XINFO                /* (not really needed) */
  33.  
  34. #ifdef LZW
  35. int LzwActive = 1;
  36. #endif
  37.  
  38. #ifdef NNTPENH
  39. int fullauto = 1;
  40. #endif
  41.  
  42. #ifdef POST_ENBL
  43. #define IHAVE_CMD    0
  44. #define POST_CMD    1
  45.  
  46. int postingok = 1;
  47. #endif
  48.  
  49. unsigned short Nntpmaxcli = 3;
  50. static unsigned short Nntpsessions = 0;
  51.  
  52.        char artmsg[]         = " Article retrieved - ";
  53. static char debug[]            = "100 DEBUG %s\n";
  54. #if (defined(POST_ENBL) && defined(XHEADER))
  55. static char help[]          = "100-ARTICLE  BODY  GROUP  HEAD  HELP  IHAVE  LAST  LIST\n"
  56.                               "100 NEWNEWS  NEXT  POST   QUIT  STAT  XHDR   XINFO\n";
  57. #elif (defined(POST_ENBL))
  58. static char help[]          = "100-ARTICLE  BODY    GROUP  HEAD  HELP  IHAVE  LAST\n"
  59.                               "100 LIST     NEWNEWS NEXT   POST  QUIT  STAT   XINFO\n";
  60. #else
  61. static char help[]          = "100-ARTICLE  BODY  GROUP    HEAD  HELP  IHAVE\n"
  62.                               "100 LAST     LIST  NEWNEWS  NEXT  QUIT  STAT   XINFO\n";
  63. #endif
  64. static char noactive[]        = "100 No active newsgroups\n";
  65. #ifdef XINFO
  66. static char xinfo[]            = "100 %s no info available\n";
  67. #endif
  68. #ifdef POST_ENBL
  69. static char nnversion[]     = "20%c %s NNTP version %s ready at %s GMT\n";
  70. #else
  71. static char nnversion[]     = "201 %s NNTP version %s ready at %s GMT\n";
  72. #endif
  73. static char slave[]            = "202 SLAVE %s\n";
  74. static char closing[]       = "205 Closing\n";
  75. static char listarticle[]    = "211 %u %u %u %s\n";
  76. static char listgrps[]        = "215 Available newsgroups\n";
  77.        char retrieve[]         = "220 %u%s%shead and body follow\n";
  78. static char head[]          = "221 %u%s%sHead\n";
  79. #ifdef XHEADER
  80. static char extrfoll[]      = "221 %s fields follow\n";
  81. #endif
  82. static char body[]          = "222 %u%s%sBody\n";
  83. static char statistics[]    = "223 %u%s%sStatistics\n";
  84. static char sepcmd[]        = "223 %u%s%srequest text separately\n";
  85. static char newnews_t[]        = "230 New news by message id follows\n";
  86. static char transok[]        = "235 Thanks\n";
  87. #ifdef POST_ENBL
  88. static char postok[]        = "240 Article posted ok\n";
  89. #endif
  90.  
  91. static char sendart[]        = "335 Send article, end with .\n";
  92. #ifdef POST_ENBL
  93. static char sendpost[]      = "340 Send article to be posted, end with .\n";
  94. #endif
  95.  
  96. static char nogroup[]        = "411 No such newsgroup\n";
  97. static char noselect[]        = "412 No newsgroup selected\n";
  98. static char nonext[]        = "421 No next article\n";
  99. static char noprev[]        = "422 No previous article\n";
  100.        char noart[]            = "430 No such article\n";
  101. static char notwanted[]        = "435 Article not wanted - do not send it\n";
  102. static char transnotok[]    = "437 Article rejected - do not try again\n";
  103. #ifdef POST_ENBL
  104. static char noposting[]     = "440 Posting not allowed\n";
  105. static char postfailed[]    = "441 Posting failed\n";
  106. #endif
  107.  
  108.        char badsyntax[]        = "501 Syntax error\n";
  109. static char error[]            = "503 Command not performed\n";
  110. static char lowmem[]         = "503 System is overloaded\n";
  111.  
  112. char NEol[]                 = ".\n";
  113.  
  114. #ifdef CONTROL
  115. static int near
  116. docontrol(FILE *f,struct nntpserv *mp)
  117. {
  118.     struct head *h;
  119.  
  120.     if(f == NULLFILE)
  121.         return -1;
  122.  
  123.     h = mxallocw(sizeof(struct head));
  124.  
  125.     rewind(f);
  126.     h->subject = h->from = h->reply_to = h->id = NULLCHAR;
  127.  
  128.     for(;;) {
  129.         if (fgets(mp->buf,LineLen,f) == NULL)
  130.             break;
  131.         if (check_blank(mp->buf))
  132.             break;
  133.         rip(mp->buf);
  134.         if (strncmp(mp->buf,Hdrs[SUBJECT],9) == 0)
  135.             h->subject = strxdup(mp->buf);
  136.         if (strncmp(mp->buf,Hdrs[FROM],6) == 0)
  137.             h->from = strxdup(mp->buf);
  138.         if (strnicmp(mp->buf,Hdrs[REPLYTO],10) == 0)
  139.             h->reply_to = strxdup(mp->buf);
  140.         if (strnicmp(mp->buf,Hdrs[MSGID],12) == 0)
  141.             h->id = strxdup(strchr(mp->buf,'<'));
  142.     }
  143.     if (h->subject != NULLCHAR)
  144.         if (strncmp(h->subject,"Subject: sendme ",16) == 0)
  145.             dosendme(h);
  146.     if (h->subject != NULLCHAR)
  147.         xfree(h->subject);
  148.     if (h->from != NULLCHAR)
  149.         xfree(h->from);
  150.     if (h->reply_to != NULLCHAR)
  151.         xfree(h->reply_to);
  152.     if (h->id != NULLCHAR)
  153.         xfree(h->id);
  154.     xfree(h);
  155.     return 0;
  156. }
  157. #endif
  158.  
  159. /* checks if newsgroup is selected
  160.  * returncode: -1 no group selected; 0 success */
  161. static int near
  162. check_grp(struct nntpserv *mp)
  163. {
  164.     if(mp->path == NULLCHAR) {
  165.         usputs(mp->s,noselect);
  166.         return -1;
  167.     }
  168.     return 0;
  169. }
  170.  
  171. static int near
  172. set_pointer(struct nntpserv *mp)
  173. {
  174.     char *cp;
  175.  
  176.     if((cp = strpbrk(mp->buf,"0123456789")) != NULLCHAR) {
  177.         int cnt = atoi(cp);
  178.         if((cnt > mp->last) || ( cnt < mp->first)) {
  179.             usputs(mp->s,noart);
  180.             return -1;
  181.         }
  182.         mp->pointer = cnt;
  183.     }
  184.     return 0;
  185. }
  186.  
  187. #ifdef POST_ENBL
  188. static void near
  189. _ihave_sub(struct nntpserv *mp,int command)
  190. {
  191.     char *cp;
  192.  
  193.     if((cp = strchr(mp->buf,'<')) == NULLCHAR) {
  194.         usputs(mp->s,badsyntax);
  195.     } else if(check_article(cp) == 1) {
  196.         usputs(mp->s,notwanted);
  197.     } else {
  198.         FILE *f;
  199.         int ret = -1;
  200.  
  201.         usputs(mp->s,sendart);
  202.  
  203.         if(mp->buf == NULLCHAR
  204.           || *(mp->buf + 1) < ' '
  205.           || (f = Tmpfile(0,1)) == NULLFILE)
  206.             return;
  207.  
  208.         if(recv_file(f,mp->s) != -1) {
  209.             char *cp;
  210.             int foundmid = 0;
  211.  
  212.             /* get id-number from article, not from IHAVE offer */
  213.             rewind(f);
  214.  
  215.             while(fgets(mp->buf,LineLen,f) != NULL) {
  216.                 rip(mp->buf);
  217.                 if(strnicmp(mp->buf,Hdrs[MSGID],12) == 0) {
  218.                     if((cp = strchr(mp->buf,'<')) != NULLCHAR) {
  219.                         mp->id = strxdup(cp);
  220.                         foundmid = 1;
  221.                         break;
  222.                     }
  223.                 }
  224.             }
  225.             /* minimum header in article required !
  226.                Now check again, if same news exists in history */
  227.             if(foundmid == 1 && check_article(mp->id) == 0 && garbled(f) == 0) {
  228.                 rewind(f);
  229.                 ret = xfer_article2(f,mp);
  230.             } else if(foundmid) {
  231.                 xfree(mp->id);
  232.             }
  233.         }
  234.         Fclose(f);
  235.         if(command == POST_CMD) {
  236.             usputs(mp->s,ret ? postfailed : postok);
  237.         } else {
  238.             usputs(mp->s,ret ? transnotok : transok);
  239.         }
  240.     }
  241.     return;
  242. }
  243. #endif
  244.  
  245. /*-------------------------- NNTP server subcmds ---------------------------*/
  246.  
  247. static void near
  248. article_command(struct nntpserv *mp)
  249. {
  250.     if(*mp->buf == '<') {
  251.         doarticle(mp,1,NULLCHAR);
  252.     } else if(check_grp(mp) == 0) {
  253.         FILE *fp;
  254.  
  255.         if(!check_blank(mp->buf)) {
  256.             if(set_pointer(mp)) {
  257.                 return;
  258.             }
  259.         }
  260.         if((fp = open_message(mp)) != NULLFILE) {
  261.             art_ret(mp,1);
  262.             sendfile(fp,mp->s,ASCII_TYPE,0x80);
  263.             usputs(mp->s,NEol);
  264.         }
  265.     }
  266.     return;
  267. }
  268.  
  269. static void near
  270. body_command(struct nntpserv *mp)
  271. {
  272.     if(check_grp(mp) == 0) {
  273.         if(set_pointer(mp) == 0) {
  274.             if(get_id(mp) == 1) {
  275.                 FILE *fp;
  276.  
  277.                 usprintf(mp->s,body,mp->pointer,mp->buf,artmsg);
  278.  
  279.                 if ((fp = open_message(mp)) != NULLFILE) {
  280.                     mp->hold_i = 0;
  281.                     while(fgets(mp->buf,LineLen,fp) != NULL) {
  282.                         if(mp->hold_i)
  283.                             usputs(mp->s,mp->buf);
  284.                         if(check_blank(mp->buf))
  285.                             mp->hold_i = 1;
  286.                     }
  287.                     Fclose(fp);
  288.                 }
  289.                 usputs(mp->s,NEol);
  290.             }
  291.         }
  292.     }
  293.     return;
  294. }
  295.  
  296. static void near
  297. debug_command(struct nntpserv *mp)
  298. {
  299.     mp->states ^= N_DEBUG;
  300.     usprintf(mp->s,debug,(mp->states & N_DEBUG) ? "ON" : "OFF");
  301.     return;
  302. }
  303.  
  304. /* Change current newsgroup */
  305. static void near
  306. group_command(struct nntpserv *mp)
  307. {
  308.     FILE *f;
  309.     char line[LineLen];
  310.  
  311.     switch(get_path(mp)) {
  312.     case 0:
  313.         usputs(mp->s,nogroup);
  314.         return;
  315.     default:
  316.         if((f = Fopen(Active,READ_TEXT,mp->s,0)) != NULLFILE) {
  317.             char *cp;
  318.             while(fgets(line,LineLen,f) != NULL) {
  319.                 if(strcspn(line," ") != strlen(mp->buf))
  320.                     continue;
  321.                 if(strnicmp(mp->buf,line,strlen(mp->buf))==0) {
  322.                     cp = strchr(line,' ');
  323.                     mp->last = atoi(cp);
  324.                     mp->first = atoi(strchr(++cp,' '));
  325.                     mp->pointer = (mp->first > mp->last ) ? 0 : mp->first;
  326.  
  327.                     usprintf(mp->s,
  328.                         listarticle,
  329.                         mp->last - mp->first + 1,
  330.                         mp->first,
  331.                         mp->last,
  332.                         mp->buf);
  333.                     Fclose(f);
  334.                     return;
  335.                 }
  336.             }
  337.             Fclose(f);
  338.         }
  339.     case -1:
  340.         usputs(mp->s,error);
  341.         return;
  342.     }
  343. }
  344.  
  345. static void near
  346. head_command(struct nntpserv *mp)
  347. {
  348.     if(check_grp(mp) == 0) {
  349.         if(set_pointer(mp) == 0) {
  350.             if(get_id(mp) == 1) {
  351.                 FILE *fp;
  352.  
  353.                 usprintf(mp->s,head,mp->pointer,mp->buf,artmsg);
  354.  
  355.                 if((fp = open_message(mp)) != NULLFILE) {
  356.                     while(fgets(mp->buf,LineLen,fp) != NULL) {
  357.                         if(check_blank(mp->buf))
  358.                             break;
  359.                         usputs(mp->s,mp->buf);
  360.                     }
  361.                     Fclose(fp);
  362.                 }
  363.                 usputs(mp->s,NEol);
  364.             }
  365.         }
  366.     }
  367.     return;
  368. }
  369.  
  370. static void near
  371. help_command(struct nntpserv *mp)
  372. {
  373.     FILE *fp;
  374.  
  375.     usprintf(mp->s,"100-%s - help follows\n",Hostname);
  376.  
  377.     if((fp = Fopen(Nhelp,READ_TEXT,0,0)) != NULLFILE ) {
  378.         sendfile(fp,mp->s,ASCII_TYPE,0x80);
  379.     } else {
  380.         usputs(mp->s,help);
  381.     }
  382.     usputs(mp->s,NEol);
  383.     return;
  384. }
  385.  
  386. #ifdef POST_ENBL
  387. static void near
  388. ihave_command(struct nntpserv *mp)
  389. {
  390.     _ihave_sub(mp,IHAVE_CMD);
  391. }
  392. #else
  393. static void near
  394. ihave_command(struct nntpserv *mp)
  395. {
  396.     char *cp;
  397.  
  398.     if((cp = strchr(mp->buf,'<')) == NULLCHAR) {
  399.         usputs(mp->s,badsyntax);
  400.     } else if(check_article(cp) == 1) {
  401.         usputs(mp->s,notwanted);
  402.     } else {
  403.         FILE *f;
  404.         int ret = -1;
  405.  
  406.         usputs(mp->s,sendart);
  407.  
  408.         if(mp->buf == NULLCHAR
  409.           || *(mp->buf + 1) < ' '
  410.           || (f = Tmpfile(0,1)) == NULLFILE)
  411.             return;
  412.  
  413.         if(recv_file(f,mp->s) != -1) {
  414.             char *cp;
  415.             int foundmid = 0;
  416.  
  417.             /* get id-number from article, not from IHAVE offer */
  418.             rewind(f);
  419.  
  420.             while(fgets(mp->buf,LineLen,f) != NULL) {
  421.                 rip(mp->buf);
  422.                 if(strnicmp(mp->buf,msgid,12) == 0) {
  423.                     if((cp = strchr(mp->buf,'<')) != NULLCHAR) {
  424.                         mp->id = strxdup(cp);
  425.                         foundmid = 1;
  426.                         break;
  427.                     }
  428.                 }
  429.             }
  430.             /* minimum header in article required !
  431.                Now check again, if same news exists in history */
  432.             if(foundmid == 1 && check_article(mp->id) == 0 && garbled(f) == 0) {
  433.                 rewind(f);
  434.                 ret = xfer_article2(f,mp);
  435.             } else if(foundmid) {
  436.                 xfree(mp->id);
  437.             }
  438.         }
  439.         Fclose(f);
  440.         usputs(mp->s,ret ? transnotok : transok);
  441.     }
  442.     return;
  443. }
  444. #endif
  445.  
  446. static void near
  447. last_command(struct nntpserv *mp)
  448. {
  449.     if(check_grp(mp) == 0) {
  450.         for (;;) {
  451.             if (mp->pointer == 0) {
  452.                 usputs(mp->s,noprev);
  453.                 return;
  454.             }
  455.             if (--mp->pointer < mp->first) {
  456.                 mp->pointer++;
  457.                 usputs(mp->s,noprev);
  458.                 return;
  459.             }
  460.             sprintf(mp->buf,"%s/%u",mp->path,mp->pointer);
  461.             if(access(mp->buf,0) == 0) {
  462.                 if(get_id(mp) == 1) {
  463.                     usprintf(mp->s,sepcmd,mp->pointer,mp->buf,artmsg);
  464.                 }
  465.                 return;
  466.             }
  467.         }
  468.     }
  469.     return;
  470. }
  471.  
  472. static void near
  473. list_command(struct nntpserv *mp)
  474. {
  475.     FILE *fp;
  476.  
  477.     if((fp = Fopen(Active,READ_TEXT,0,0)) != NULLFILE) {
  478.         usputs(mp->s,listgrps);
  479.         sendfile(fp,mp->s,ASCII_TYPE,0x80);
  480.         usputs(mp->s,NEol);
  481.     } else {
  482.         usputs(mp->s,noactive);
  483.     }
  484.     return;
  485. }
  486.  
  487. static void near
  488. newnews_command(struct nntpserv *mp)
  489. {
  490.     FILE *f;
  491.  
  492.     if((f = Tmpfile(mp->s,1)) != NULLFILE) {
  493.         int ret = newnews(mp,f);
  494.  
  495.         switch(ret) {
  496.         case -1:                        /* error in "newnews" routine */
  497.             ret = 0;
  498.             usputs(mp->s,badsyntax);
  499.             break;
  500.         default:
  501.             usputs(mp->s,newnews_t);
  502.             if(ret) {
  503.                 ret = (int)sendfile(f,mp->s,ASCII_TYPE,0);
  504.             }
  505.             if(ret != -1) {
  506.                 usputs(mp->s,NEol);
  507.             }
  508.             break;
  509.         }
  510.         Fclose(f);
  511.     }
  512.     return;
  513. }
  514.  
  515. static void near
  516. next_command(struct nntpserv *mp)
  517. {
  518.     if(check_grp(mp) == 0) {
  519.         for (;;) {
  520.             if(mp->pointer == 0 ) {
  521.                 usputs(mp->s,nonext);
  522.                 return;
  523.             }
  524.             if(++mp->pointer > mp->last) {
  525.                 mp->pointer--;
  526.                 usputs(mp->s,nonext);
  527.                 return;
  528.             }
  529.             sprintf(mp->buf,"%s/%u",mp->path,mp->pointer);
  530.             if(access(mp->buf,0) == 0) {
  531.                 if(get_id(mp) == 1) {
  532.                     usprintf(mp->s,sepcmd,mp->pointer,mp->buf,artmsg);
  533.                 }
  534.                 return;
  535.             }
  536.         }
  537.     }
  538.     return;
  539. }
  540.  
  541. #ifdef POST_ENBL
  542. static void near
  543. post_command(struct nntpserv *mp)
  544. {
  545.     if(postingok) {
  546.         usputs(mp->s,sendpost);
  547.         _ihave_sub(mp,POST_CMD);
  548.     } else {
  549.         usputs(mp->s,noposting);
  550.     }
  551.     return;
  552. }
  553. #endif
  554.  
  555. static void near
  556. quit_command(struct nntpserv *mp)
  557. {
  558.     usputs(mp->s,closing);
  559.     mp->states = CLOSED;
  560.     return;
  561. }
  562.  
  563. static void near
  564. slave_command(struct nntpserv *mp)
  565. {
  566.     mp->states ^= N_SLAVE;
  567.     usprintf(mp->s,slave,(mp->states & N_SLAVE) ? "ON" : "OFF");
  568.     return;
  569. }
  570.  
  571. static void near
  572. stat_command(struct nntpserv *mp)
  573. {
  574.     if(check_grp(mp) == 0) {
  575.         if(set_pointer(mp) == 0) {
  576.             if(get_id(mp) == 1) {
  577.                 usprintf(mp->s,statistics,mp->pointer,mp->buf,artmsg);
  578.             }
  579.         }
  580.     }
  581.     return;
  582. }
  583.  
  584. #ifdef XHEADER
  585. static void near
  586. xhdr_command(struct nntpserv *mp)
  587. {
  588.     FILE *fp;
  589.     char c = 0, fname[MAXPATH + 10], t[20];
  590.     int    first = 0, last = 0, t_len;
  591.  
  592.     /* It must be a range of articles, which means that we need
  593.      * to be in a newsgroup already. */
  594.     if(check_grp(mp) == -1) {
  595.         return;
  596.     }
  597.     if(mp->pointer == 0) {
  598.         usputs(mp->s,noart);
  599.         return;
  600.     }
  601.     /* Handle message-id requests */
  602.     if(strchr(mp->buf,'<') != NULLCHAR) {
  603.         doarticle(mp,1,NULLCHAR);
  604.         return;
  605.     }
  606.     if(sscanf(mp->buf,"%18s %d%c%d",t,&first,&c,&last) < 2) {
  607.         usputs(mp->s,badsyntax);
  608.         return;
  609.     }
  610.     t_len = strlen(t);
  611.  
  612.     if(first < mp->first) {
  613.         first = mp->first;
  614.     }
  615.     if(!c) {
  616.         last = first;
  617.     }
  618.     if(!last || last > mp->last) {
  619.         last = mp->last;
  620.     }
  621.     if(first > last) {
  622.         first = last;
  623.     }
  624.     usprintf(mp->s,extrfoll,strupr(t));
  625.  
  626.     do {
  627.         mp->pointer = first;
  628.  
  629.         sprintf(fname,"%s/%u",mp->path,mp->pointer);
  630.  
  631.         if((fp = Fopen(fname,READ_TEXT,0,0)) != NULLFILE) {
  632.             while(fgets(mp->buf,LineLen,fp) != NULL) {
  633.                 if(*mp->buf == '\n' || *mp->buf == '\0') {
  634. /*                    usprintf(mp->s,"%d (none)\n",mp->pointer);    */
  635.                     break;
  636.                 }
  637.                 if(strnicmp(t,mp->buf,t_len) == 0) {
  638.                     char *cp = strchr(mp->buf,' ');
  639.                     usprintf(mp->s,"%d %s",mp->pointer,cp + 1);
  640.                     break;
  641.                 }
  642.             }
  643.             Fclose(fp);
  644.         }
  645.     } while(first++ < last);
  646.  
  647.     usputs(mp->s,NEol);
  648. }
  649. #endif
  650.  
  651. #ifdef XINFO
  652. static void near
  653. xinfo_command(struct nntpserv *mp)
  654. {
  655.     FILE *fp;
  656.  
  657.     if((fp = Fopen(NInfo,READ_TEXT,0,0)) != NULLFILE ) {
  658.         usprintf(mp->s,"100-%s - info follows\n",Hostname);
  659.         sendfile(fp,mp->s,ASCII_TYPE,0x80);
  660.     } else {
  661.         usprintf(mp->s,xinfo,Hostname);
  662.     }
  663.     usputs(mp->s,NEol);
  664.     return;
  665. }
  666. #endif
  667.  
  668. #ifdef LZW
  669. static void near
  670. xlzw_command(struct nntpserv *mp)
  671. {
  672.      if(LzwActive) {
  673.         int lzwbits = 99;
  674.         int lzwmode = -1;
  675.         sscanf(mp->buf,"%d %d",&lzwbits,&lzwmode);
  676.  
  677.         if(lzwbits > lzwmode && 9 < lzwbits && lzwbits < 17
  678.           && (lzwmode == 0 || lzwmode == 1)) {
  679.             usputs(mp->s,transok);
  680.             lzwinit(mp->s,lzwbits,lzwmode);
  681.         } else {
  682.             usputs(mp->s,error);
  683.         }
  684.      }
  685. }
  686. #endif
  687.  
  688. void
  689. nntpserv(int s,void *unused,void *p)
  690. {
  691.     /* Command table */
  692.     static struct cmdtable {
  693.         char *name;
  694.         void near (*func) __ARGS((struct nntpserv *mp));
  695.         int states;
  696.     } cmdtable[] = {
  697.         {"ARTICLE",        article_command,    0},
  698.         {"BODY",        body_command,        0},
  699.         {"DEBUG",        debug_command,        0},
  700.         {"GROUP",        group_command,        0},
  701.         {"HEAD",        head_command,        0},
  702.         {"HELP",        help_command,        0},
  703.         {"IHAVE",        ihave_command,        0},
  704.         {"LAST",        last_command,        0},
  705.         {"LIST",        list_command,        0},
  706.         {"NEWNEWS",     newnews_command,    0},
  707.         {"NEXT",        next_command,        0},
  708. #ifdef POST_ENBL
  709.         {"POST",        post_command,        0},
  710. #endif
  711.         {"QUIT",        quit_command,        0},
  712.         {"SLAVE",        slave_command,        0},
  713.         {"STAT",        stat_command,        0},
  714. #ifdef XHEADER
  715.         {"XHDR",        xhdr_command,        0},
  716. #endif
  717. #ifdef XINFO
  718.         {"XINFO",        xinfo_command,        0},
  719. #endif
  720. #ifdef LZW
  721.         {"XLZW",        xlzw_command,        0},
  722. #endif
  723.         {0, 0, 0},
  724.     };
  725.     struct cmdtable *cmdp;
  726.  
  727.     int arglen;
  728.     char *cp, *cp1;
  729.     struct nntpserv *mp;
  730.  
  731.     sockowner(s,Curproc);        /* We own it now */
  732.     sockmode(s,SOCK_ASCII);
  733.  
  734.     if(!Filecheck)
  735.         if(check_system()) {
  736.             usputs(s,"503 Fatal error in structure\n");
  737.             close_s(s);
  738.             return;
  739.         }
  740.  
  741.     cp = ctime(&currtime);
  742.     cp[24] = '\0';
  743.  
  744. #ifdef POST_ENBL
  745.     usprintf(s,nnversion,postingok ? '0' : '1',Hostname,Version,cp);
  746. #else
  747.     usprintf(s,nnversion,Hostname,Version,cp);
  748. #endif
  749.  
  750.     if(++Nntpsessions > Nntpmaxcli) {
  751.         usputs(s,lowmem);
  752.         close_s(s);
  753.         return;
  754.     }
  755.  
  756.     mp = mxallocw(sizeof(struct nntpserv));
  757.     mp->buf = mxallocw(LineLen);
  758.     mp->s = s;
  759.  
  760.     log(mp->s,9983,"NNTP open");
  761.  
  762.     for( ; ;) {
  763. loop:
  764.         if(mp->states == CLOSED) {
  765.             break;
  766.         }
  767.         if(recvline(mp->s,mp->buf,LineLen) <= 0) {
  768.             /* He closed on us */
  769.             break;
  770.         }
  771.         rip(mp->buf);
  772.  
  773.         arglen = 0;
  774.         cp = mp->buf;
  775.  
  776.         while(isspace(*cp)) {
  777.             cp++;
  778.         }
  779.         cp1 = cp;
  780.  
  781.         while(*cp1 != '\0' && !isspace(*cp1)) {
  782.             cp1++;
  783.             arglen++;
  784.         }
  785.         if(arglen) {
  786.             for(cmdp = cmdtable; cmdp->name; cmdp++) {
  787.                 if(strnicmp(cmdp->name,cp,arglen) == 0) {
  788.                     char *line, *cp2 = cp1;
  789.  
  790.                     while(*cp2 != '\0' && isspace(*cp2)) {
  791.                         cp2++;
  792.                     }
  793.                     line = strxdup(cp2);
  794.  
  795.                     /* Translate entire buffer to lower case */
  796.                     strlwr(line);
  797.                     strcpy(mp->buf,line);
  798.                     xfree(line);
  799.  
  800.                     pwait(NULL);    /* TEST */
  801.  
  802.                     (*cmdp->func)(mp);
  803.                     goto loop;
  804.                 }
  805.             }
  806.         }
  807.         /* Can't be a legal command */
  808.         usputs(mp->s,error);
  809.     }
  810. quit:
  811.     log(mp->s,9983,"NNTP close");
  812.     close_s(mp->s);
  813.  
  814.     Nntpsessions--;
  815.  
  816.     if(mp->path != NULLCHAR) {
  817.         xfree(mp->path);
  818.     }
  819.     if(mp->newnews != NULLCHAR) {
  820.         xfree(mp->newnews);
  821.     }
  822.     xfree(mp->buf);
  823.     xfree(mp);
  824. }
  825.  
  826. /* ---------------------------- SMTP->NNTP-GATE --------------------------- */
  827.  
  828. int
  829. nnGpost(FILE *data,char *from,struct list *le)
  830. {
  831.     FILE *f;
  832.     struct nntpserv *mp;
  833.     int msgidfound = 0;
  834.     char buf[LineLen], *cp, *cp1;
  835.  
  836.     if (!Filecheck)
  837.         if(check_system())
  838.             return -1;
  839.  
  840.     if ((f = Tmpfile(0,1)) == NULLFILE)
  841.         return -1;
  842.  
  843.     mp = mxallocw(sizeof(struct nntpserv));
  844.  
  845.     /* build path */
  846.     cp = strxdup(from);
  847.  
  848.     if((cp1 = strpbrk(cp,"@. ")) != NULLCHAR)
  849.         *cp1 = '\0';
  850.  
  851.     cp1 = strxdup(cp);
  852.  
  853.     if(strchr(cp1,'%') != NULLCHAR) {
  854.         char *cp2, *revpath = strxdup(cp1);
  855.  
  856.         *cp1 = '\0';
  857.  
  858.         while((cp2 = strrchr(revpath,'%')) != NULLCHAR) {
  859.             *cp2++ = '\0';
  860.             strcat(cp1,cp2);
  861.             strcat(cp1,"!");
  862.         }
  863.         strcat(cp1,revpath);
  864.         xfree(revpath);
  865.     }
  866.     fprintf(f,"%s%s\n",Hdrs[PATH],cp1);
  867.     xfree(cp1);
  868.  
  869.     /* look for msg-id */
  870.     rewind(data);
  871.     while(fgets(buf,LineLen,data) != NULL)   {
  872.         if(*buf == '\t' || *buf == ' ')
  873.             continue;
  874.         rip(buf);
  875.         if(*buf == '\0')
  876.             break;
  877.         if(htype(buf) == MSGID) {
  878.             msgidfound = 1;
  879.             break;
  880.         }
  881.     }
  882.  
  883.     /* reorganize header */
  884.     rewind (data);
  885.     while(fgets(buf,LineLen,data) != NULL)   {
  886.         if(*buf == '\t' || *buf == ' ')
  887.             continue;
  888.         rip(buf);
  889.         if(*buf == '\0')
  890.             break;
  891.         switch(htype(buf)) {
  892.         case FROM:
  893.             /* generating from line */
  894.             fprintf(f,"%s%s@%s",Hdrs[FROM],cp,Hostname);
  895.             if((cp1 = strpbrk(buf,"<(")) != NULLCHAR)
  896.                 fprintf(f," %s",cp1);
  897.  
  898.             /* generating newsgroups line */
  899.             if((cp1 = strpbrk(&le->val[1],"!@")) != NULLCHAR)
  900.                 *cp1 = '\0';
  901.             fprintf(f,"\n%s%s\n",Hdrs[NEWSGROUPS],&le->val[1]);     /* skip the bang */
  902.             continue;
  903.         case SUBJECT:
  904.             fprintf(f,"%s\n",strlen(buf) < 10 ? "Subject: (none)" : buf);
  905.             if(msgidfound == 0) {
  906.                 sprintf(mp->buf,"<%ld@%s>",get_msgid(),Hostname);
  907.                 fprintf(f,"%s%s\n",Hdrs[MSGID],mp->buf);
  908.                 mp->id = strxdup(mp->buf);
  909.             }
  910.             fprintf(f,"Sender: NNTP@%s\n",Hostname);
  911.             continue;
  912.         case MSGID:
  913.             if(msgidfound == 1) {
  914.                 fprintf(f,"%s\n",buf);
  915.                 if((cp1 = strchr(buf,'<')) != NULLCHAR) {
  916.                     sprintf(mp->buf,"%s",cp1);
  917.                     mp->id = strxdup(cp1);
  918.                 }
  919.             }
  920.             continue;
  921.         case TO:
  922.         case RECEIVED:
  923.         case SENDER:
  924.         case STATUS:
  925.         case NOHEADER:
  926.             continue;
  927.         }
  928.         fprintf(f,"%s\n",buf);
  929.     }
  930.     xfree(cp);
  931.  
  932.     fputc('\n',f);
  933.  
  934.     while(fgets(buf,LineLen,data) != NULL)
  935.         fputs(buf,f);
  936.  
  937.     fflush(f);
  938.     rewind(f);
  939.     xfer_article2(f,mp);
  940.     Fclose(f);
  941.     xfree(mp);
  942.     return 0;
  943. }
  944.  
  945. #endif /* NNTP */
  946.